package com.xxx.springboot.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;

import java.util.concurrent.ThreadPoolExecutor;

/**
 * https://www.toutiao.com/i6807650160445751820
 * springboot 线程池配置
 * 线程池原理：
 * 1.线程池初始化时，线程池中的线程数为0，当有任务来执行时，会创建一个线程去执行该任务；
 * 2.当线程池中的线程数量达到corePoolSize时，会将任务放入等待队列中；
 * 3.当等待队列满时，会继续创建新的线程，来执行队列中的任务；
 * 4.当线程池中的线程数达到maxPoolSize时，会根据拒绝策略进行拒绝。
 * 
 * 通过线程池执行异步任务步骤：
 * ① Application开启@EnableAsync注解，目的是开启@Async注解
 * ② 配置线程池：ThreadPoolTaskConfig
 * ③ 在发送短信服务SendMessageService里开启异步任务注解 @Async("taskExecutor")
 * ④ 在订单服务OrderService里调用发送短信服务方法，就会让线程池来异步执行
 */
@Configuration
public class ThreadPoolTaskConfig {

    @Bean("taskExecutor") // bean的名称，默认为首字母小写的方法名
    public ThreadPoolTaskExecutor taskExecutor() {
    	ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor();
    	taskExecutor.setCorePoolSize(20);       // 核心线程数（默认线程数）
    	taskExecutor.setMaxPoolSize(100);       // 最大线程数
    	taskExecutor.setQueueCapacity(200);     // 缓冲队列大小
    	taskExecutor.setKeepAliveSeconds(10);   // 线程空闲时间（单位：秒）
    	// 线程池拒绝策略：由调用线程（提交该任务的线程）去执行该任务
    	taskExecutor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
        taskExecutor.setWaitForTasksToCompleteOnShutdown(true); // 等待任务完成再销毁
    	taskExecutor.setThreadNamePrefix("taskExecutor-");     // 线程池名前缀
    	taskExecutor.initialize();  // 线程池初始化
    	return taskExecutor;
    }

    @Bean
    public ThreadPoolTaskExecutor defaultTaskExecutor() {
        ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor();
        taskExecutor.setCorePoolSize(8);            // 核心线程数（默认线程数）
        taskExecutor.setMaxPoolSize(200);           // 最大线程数
        taskExecutor.setQueueCapacity(1000);        // 缓冲队列大小
        taskExecutor.setKeepAliveSeconds(60);       // 线程空闲时间（单位：秒）
        // 拒绝策略，由调用线程阻塞执行
        taskExecutor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
        taskExecutor.setWaitForTasksToCompleteOnShutdown(true);   // 等待任务完成再销毁
        taskExecutor.setThreadNamePrefix("defaultTaskExecutor-");
        taskExecutor.initialize();  // 线程池初始化
        return taskExecutor;
    }

}
